# -*- coding: utf-8 -*-
import pygame
import event
import logging

class Dispatcher:
    '''
    事件分发器
    注意只能用于单线程情况，没有多线程的安全考虑
    '''
    def __init__(self):
        self.__filter_stack = {}
    
    def dispatch(self, h_event):
        if not h_event.type() in self.__filter_stack:
            return
        h_events = [h_event]
        for filter in self.__filter_stack[h_event.type()]:
            continue_events = []
            for e in h_events:
                result_events = filter.handle(e)
                for r_event in result_events:
                    state = r_event.get_state()
                    if state == event.CONTINUE_HANDLE:
                        continue_events.append(r_event)
                    elif state == event.ERROR_HAPPENED:
                        logging.warning(r_event.error_msg)
                        continue
                    elif state == event.HANDLED:
                        continue
                    else:
                        logging.warning("Unknown h_event state %d in %s" % \
                                    (state, str(r_event)))
                        continue
            h_events = continue_events
    
    def attach(self, event_id, filter):
        '''
        将filter加入到event_id事件的过滤处理堆栈当中
        如果filter不能处理event_id事件，则抛出TypeError异常
        event_id:要加入到的事件过滤处理堆栈的事件id
        filter:要加入的过滤器对象
        返回：None
        '''
        #先检查filter是否能够处理event_id，如果不能的话，抛出异常
        if not filter.match(event_id):
            e_msg = "Filter type %s instance %s cannot handle event %d." % \
                (str(filter.__class__), str(filter), event_id)
            raise TypeError(e_msg)
        if not event_id in self.__filter_stack:
            self.__filter_stack[event_id] = []
        self.__filter_stack[event_id].insert(0, filter)
        #调用filter的钩子函数，通知其已经挂接好了
        filter.attached(self, event_id)
    
    def deattach(self, event_id, filter):
        '''
        将filter从event_id事件对应的过滤处理堆栈当中移除
        event_id:所要处理的过滤处理堆栈的事件id
        filter:要移除的过滤器
        返回：如果成功移除则返回该filter对象，否则返回None
        '''
        if not event_id in self.__filter_stack:
            return None
        try:
            self.__filter_stack[event_id].remove(filter)
        except ValueError,data:
            return None
        filter.deattached(self, event_id)
        return filter
        
        